package com.gxs.tga.poc.rest;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.gxs.tga.poc.domain.TgaSolution;
import com.gxs.tga.poc.domain.TgaSolutionTP;
import com.gxs.tga.poc.domain.dto.TgaSolutionTPDto;
import com.gxs.tga.poc.domain.exceptions.DuplicateTgaSolution;
import com.gxs.tga.poc.domain.exceptions.DuplicateTgaSolutionTP;
import com.gxs.tga.poc.domain.exceptions.InvalidClientRequest;
import com.gxs.tga.poc.rest.common.TgaRestResponse;
import com.gxs.tga.poc.service.TgaSolutionService;
import com.gxs.tga.poc.service.TgaSolutionTPService;

@Component("tgaSolutionTPRestBean")
@Path("/solutions/{solutionId}/tradingPartners")
public class TgaSolutionTPRestBean
{
	@Autowired
	private TgaSolutionTPService tgaSolutionTPService;
	
	@Autowired
	private TgaSolutionService tgaSolutionService;

	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response getAllTradingPartnersForSolution(@PathParam("solutionId") String solutionId)
	{

		try
		{
			TgaSolution solution = this.tgaSolutionService.findById(solutionId);
			
			if(solution== null)
			{
				throw new InvalidClientRequest("Error: NO solution was found with the given solutionId: " + solutionId);
			}
			
			List<TgaSolutionTP> list = this.tgaSolutionTPService.findByTgaSolution(solution);
			List<TgaSolutionTPDto> returnList = new ArrayList<TgaSolutionTPDto>();
			
			for(TgaSolutionTP partner : list)
			{
				returnList.add(new TgaSolutionTPDto(partner));
			}
			return Response.status(Status.OK).entity(returnList).build();
		}
		catch(Exception e)
		{
			e.printStackTrace();
			int statusCode = 500;
			TgaRestResponse response = new TgaRestResponse(statusCode, "Error Occurred: " + e.getMessage(), statusCode);
			return Response.status(statusCode).entity(response).build();
		}
	}

	@GET
	@Path("/{tpRecordId}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getSingleTradingPartnerRecordFromSolution(@PathParam("tpRecordId") String tpRecordId)
	{
		TgaSolutionTP tgaSolutionTp = this.tgaSolutionTPService.findById(tpRecordId);
		
		if (tgaSolutionTp == null)
		{
			int statusCode = 404;
			TgaRestResponse response = new TgaRestResponse(statusCode, "No record of type 'TgaSolutionTP' (Trading Partner) exists with the id: " + tpRecordId, statusCode);
			return Response.status(statusCode).entity(response).build();
		} else
		{
			TgaSolutionTPDto dto = new TgaSolutionTPDto(tgaSolutionTp);
			return Response.status(200).entity(dto).build();
		}

	}

	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	public Response createOrUpdateTest(TgaSolutionTPDto tradingPartnerDTO, @PathParam("solutionId") String solutionId, @QueryParam("operation") String operation) throws InvalidClientRequest 
	{
		
		if(operation == null )
		{
			throw new InvalidClientRequest("Missing Query Parameter: 'operation' -- must be provided. Valid Values are: [create, update]");
		}
		else if(operation.equals("create") || operation.equals("update"))
		{
			// good
		}
		else
		{
			throw new InvalidClientRequest("Incorrect value for Query Parameter: 'operation' -- must be provided. Valid Values are: [create, update]");
		}
 
		if(operation.equals("update"))
		{
			throw new InvalidClientRequest("Work In Progress: Update operation is currently in development");
		}
		
		try
		{
			// First check that the specific solution exists
			
			if(tradingPartnerDTO.getSolutionId() != null )
			{
				throw new InvalidClientRequest("Error: solution id is taken from the path and should not be provided in the input JSON object");
			}
			
			if(tradingPartnerDTO.getTpRecordId() != null)
			{
				throw new InvalidClientRequest("Error: TPRecordId attribute is dynamically generated as primary key and should not be provided in the input data");
			}
			
			TgaSolution solution = this.tgaSolutionService.findById(solutionId);
			
			if(solution == null)
			{
				throw new InvalidClientRequest("Error: Given solution id: '" + solutionId + "' does not exist");
			}
			
			List<TgaSolutionTP> tpList = this.tgaSolutionTPService.findByCompIdAndTgaSolution(tradingPartnerDTO.getCompId(), solution);
			
			if(tpList != null && tpList.size() > 0)
			{
				throw new InvalidClientRequest("Error: The given company with company id: " + tradingPartnerDTO.getCompId() + " already has been included in this solution as a trading partner");
			}
			
			TgaSolutionTP tp = new TgaSolutionTP(tradingPartnerDTO, solution, true);
			
			this.tgaSolutionTPService.create(tp);
			
			int statusCode  = Response.Status.CREATED.getStatusCode();
			
			TgaSolutionTPDto dtoToReturn = new TgaSolutionTPDto(tp) ;
			
			TgaRestResponse response = new TgaRestResponse(statusCode, "A Tading Partner association with tpRecordId " + tp.getTpRecordId() + " has been created");
			response.setTargetResource(dtoToReturn);
			response.setTargetResourceRefId(tp.getTpRecordId());
			response.setTargetResourcePKAttributeName("tpRecordId");
			
			return Response.status(statusCode).entity(    response         ).build();
		}
		catch(DuplicateTgaSolutionTP dte)
		{
			int statusCode  = Response.Status.CONFLICT.getStatusCode();
			TgaRestResponse response = new TgaRestResponse(statusCode, "Error: Trading Partner with record id: " + tradingPartnerDTO.getTpRecordId() +  ", and company id: " +  tradingPartnerDTO.getCompId() +" already exists" , statusCode);
			return Response.status(statusCode).entity(response).build();

		}
		
		
	}
 
}
